<template>
  <el-upload class="upload-demo" :on-preview="handlePreview" :on-remove="handleRemove" :file-list="fileList"
    list-type="picture" :auto-upload="false" :http-request="customUpload" ref="uploadRef">
    <el-button size="small" type="primary">粘贴或点击上传文件</el-button>
  </el-upload>
</template>

<script>

export default {
  props: {
    // 当父组件发送清空文件列表信号时，执行相应动作。
    clear_file_list: {
      type: Boolean,
      default: false
    }

  },
  data() {
    return {
      fileList: [],
      uploadedBlobUrls: new Set(),
      uploadingUids: new Set()
    };
  },
  mounted() {
    document.addEventListener('paste', this.handlePaste, true);
  },
  beforeDestroy() {
    document.removeEventListener('paste', this.handlePaste, true);
    this.fileList.forEach(file => {
      if (file.url?.startsWith('blob:')) URL.revokeObjectURL(file.url);
    });
    this.uploadedBlobUrls.clear();
    this.uploadingUids.clear();
  },
  methods: {
    handleRemove(file, fileList) {
      if (file.url?.startsWith('blob:')) {
        URL.revokeObjectURL(file.url);
        this.uploadedBlobUrls.delete(file.url);
      }
      this.uploadingUids.delete(file.uid);
      this.fileList = fileList;
      console.log('文件移除：', file);
    },
    handlePreview(file) {
      console.log('预览文件：', file);
    },

    // 🔴 核心：自定义上传逻辑（完全绕过el-upload的状态管理）
    async customUpload(params) {
      const file = params.file;
      const fileUid = file.uid;

      try {
        // 构造FormData（模拟el-upload的默认上传格式）
        const formData = new FormData();
        formData.append('file', file.raw, file.name); // 第三个参数是文件名（含后缀）

        // 标记为上传中
        this.uploadingUids.add(fileUid);
        const index = this.fileList.findIndex(item => item.uid === fileUid);
        if (index !== -1) {
          this.$set(this.fileList[index], 'status', 'uploading');
        }

        // 直接用axios请求后端（避免el-upload的内部干扰）
        const response = await this.$axios.post(
          '/api/todo/upload',
          formData,
          {
            headers: { 'Content-Type': 'multipart/form-data' }, // 必须设置该头
            onUploadProgress: (progressEvent) => {
              // （可选）上传进度反馈
              const percent = Math.round((progressEvent.loaded / progressEvent.total) * 100);
              console.log(`文件${file.name}上传进度：${percent}%`);
            }
          }
        );

        // 上传成功处理
        if (response.data?.code === 200) {
          this.$message.success(`文件${file.name}上传成功！`);
          this.uploadingUids.delete(fileUid);
          this.uploadedBlobUrls.add(file.url);

          // 用后端返回的永久URL替换Blob URL
          if (response.data.data?.file_url) {
            this.$emit('upload-success-url', response.data.data.file_url)
            if (index !== -1) {
              this.$set(this.fileList[index], 'url', response.data.data.file_url);
              this.$set(this.fileList[index], 'status', 'success'); // 手动设置成功状态
              // 释放Blob URL内存
              if (file.url?.startsWith('blob:')) {
                URL.revokeObjectURL(file.url);
              }
            }
          }
        } else {
          throw new Error(response.data?.msg || '上传失败');
        }
      } catch (error) {
        // 上传失败处理
        this.$message.error(`文件${file.name}上传失败：${error.message}`);
        console.error('上传失败详情：', error);
      }
    },

    async handlePaste(e) {
      try {
        e.preventDefault();
        e.stopPropagation();

        const eventClipboard = e.clipboardData || window.clipboardData;
        if (!eventClipboard) {
          this.$message.warning('浏览器不支持剪贴板操作');
          return;
        }

        // 关键：从剪贴板获取 HTML 数据（图片可能藏在里面）
        const html = eventClipboard.getData('text/html');
        if (!html) {
          // 若没有 HTML，尝试直接获取文件（比如从文件夹复制图片）
          const files = eventClipboard.files || [];
          if (files.length > 0) {
            this.handlePastedFiles(Array.from(files));
          } else {
            this.$message.info('剪贴板中没有可粘贴的图片');
          }
          return;
        }

        // 解析 HTML 中的 Base64 图片（核心逻辑）
        const imageBase64List = this.extractBase64FromHtml(html);
        if (imageBase64List.length === 0) {
          this.$message.info('剪贴板中没有可粘贴的图片');
          return;
        }

        // 处理每个 Base64 图片
        for (const base64 of imageBase64List) {
          const blob = this.base64ToBlob(base64);
          this.handleSingleImageBlob(blob);
        }
      } catch (error) {
        console.error('粘贴处理失败', error);
        this.$message.error('图片粘贴失败，请尝试其他方式上传');
      }
    },

    // 辅助函数1：从 HTML 中提取 Base64 图片（匹配 <img src="data:image/...">）
    extractBase64FromHtml(html) {
      const base64Regex = /<img[^>]+src="(data:image\/[^;]+;base64,[^"]+)"/g;
      const result = [];
      let match;
      while ((match = base64Regex.exec(html)) !== null) {
        result.push(match[1]);
      }
      return result;
    },

    // 辅助函数2：Base64 转 Blob（用于后续上传）
    base64ToBlob(base64) {
      const [meta, data] = base64.split(',');
      const mime = meta.match(/:(.*?);/)[1]; // 提取 MIME 类型（如 image/png）
      const byteString = atob(data); // Base64 解码
      const arrayBuffer = new ArrayBuffer(byteString.length);
      const uint8Array = new Uint8Array(arrayBuffer);

      for (let i = 0; i < byteString.length; i++) {
        uint8Array[i] = byteString.charCodeAt(i);
      }

      return new Blob([uint8Array], { type: mime });
    },

    // 辅助函数3：处理直接粘贴的文件（如从文件夹复制图片）
    handlePastedFiles(files) {
      const imageFiles = files.filter(file => file.type.startsWith('image/'));
      if (imageFiles.length === 0) {
        this.$message.info('剪贴板中没有可粘贴的图片');
        return;
      }
      imageFiles.forEach(file => this.handleSingleImageBlob(file));
    },

    // 辅助函数4：统一处理图片 Blob（复用原逻辑）
    handleSingleImageBlob(blob) {


      const fileExt = blob.type.split('/')[1] || 'png';
      const fileName = `paste-${Date.now()}.${fileExt}`;
      const fileUid = Date.now() + Math.floor(Math.random() * 10000);
      const blobUrl = URL.createObjectURL(blob);

      // 避免重复（复用原逻辑）
      if (this.uploadedBlobUrls.has(blobUrl) || this.uploadingUids.has(fileUid)) {
        this.$message.info('该图片已在上传中或已上传，无需重复操作');
        return;
      }
      if (this.fileList.some(file => file.url === blobUrl)) return;

      // 构造文件对象并上传（复用原逻辑）
      const newFile = {
        uid: fileUid,
        name: fileName,
        url: blobUrl,
        raw: blob,
        status: 'ready',
        isPasted: true,
        size: blob.size,
        type: blob.type
      };

      this.fileList = [...this.fileList, newFile];
      this.$message.success('图片粘贴成功，正在自动上传...');
      setTimeout(() => {
        this.customUpload({ file: newFile });
      }, 100);
    }
  },
  watch: {
    clear_file_list(newVal) {
      if (newVal) {
        this.fileList = []
        this.$emit('file_list_status', false)
      }
    }
  }
};
</script>

<style scoped>
.upload-demo {
  margin-bottom: 20px;
}
</style>